home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / sockuser.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  12KB  |  572 lines

  1. /****************************************************************************
  2. *    sockuser.c
  3. *    $Id: sockuser.c 1.3 94/01/04 14:10:37 ROOT_DOS Exp $
  4. *                                                                    
  5. *    01 Apr 93    1.2        GT    recvchar () - skip ^Z in ASCII mode.
  6. *    07 Nov 93    1.3        GT    Redisplay "net>" prompt in command session.
  7. *
  8. *  ATARI Version by David Nash - dnash@chaos.demon.co.uk
  9. *
  10. ****************************************************************************/
  11.  
  12. /* Higher level user subroutines built on top of the socket primitives
  13.  * Copyright 1991 Phil Karn, KA9Q
  14.  */
  15. #include "global.h"
  16. #include "main.h"
  17. #ifdef    ANSIPROTO
  18. #include <stdarg.h>
  19. #endif
  20. #include "mbuf.h"
  21. #include "proc.h"
  22. #include "socket.h"
  23. #include "usock.h"
  24. #include "session.h"
  25. #include "nr4.h"
  26.  
  27.  
  28. /* Higher-level receive routine, intended for connection-oriented sockets.
  29.  * Can be used with datagram sockets, although the sender id is lost.
  30.  */
  31. int
  32. recv(s,buf,len,flags)
  33. int s;        /* Socket index */
  34. char *buf;    /* User buffer */
  35. int len;    /* Max length to receive */
  36. int flags;    /* Unused; will eventually select oob data, etc */
  37. {
  38.     struct mbuf *bp;
  39.     int cnt;
  40.  
  41.     if(len == 0)
  42.         return 0;    /* Otherwise would be interp as "all" */
  43.  
  44.     cnt = recv_mbuf(s,&bp,flags,NULLCHAR,(int *)NULL);
  45.     if(cnt > 0){
  46.         cnt = min(cnt,len);
  47.         pullup(&bp,buf,(int16)cnt);
  48.         free_p(bp);
  49.     }
  50.     return cnt;
  51. }
  52. /* Higher level receive routine, intended for datagram sockets. Can also
  53.  * be used for connection-oriented sockets, although from and fromlen are
  54.  * ignored.
  55.  */
  56. int
  57. recvfrom(s,buf,len,flags,from,fromlen)
  58. int s;        /* Socket index */
  59. char *buf;    /* User buffer */
  60. int len;    /* Maximum length */
  61. int flags;    /* Unused; will eventually select oob data, etc */
  62. char *from;    /* Source address, only for datagrams */
  63. int *fromlen;    /* Length of source address */
  64. {
  65.     struct mbuf *bp;
  66.     register int cnt;
  67.  
  68.     cnt = recv_mbuf(s,&bp,flags,from,fromlen);
  69.     if(cnt > 0){
  70.         cnt = min(cnt,len);
  71.         pullup(&bp,buf,(int16)cnt);
  72.         free_p(bp);
  73.     }
  74.     return cnt;
  75. }
  76. /* High level send routine */
  77. int
  78. send(s,buf,len,flags)
  79. int s;        /* Socket index */
  80. char *buf;    /* User buffer */
  81. int len;    /* Length of buffer */
  82. int flags;    /* Unused; will eventually select oob data, etc */
  83. {
  84.     register struct mbuf *bp;
  85.     char sock[MAXSOCKSIZE];
  86.     int i = MAXSOCKSIZE;
  87.  
  88.     if(getpeername(s,sock,&i) == -1)
  89.         return -1;
  90.     bp = qdata(buf,(int16)len);
  91.     return send_mbuf(s,bp,flags,sock,i);
  92. }
  93. /* High level send routine, intended for datagram sockets. Can be used on
  94.  * connection-oriented sockets, but "to" and "tolen" are ignored.
  95.  */
  96. int
  97. sendto(s,buf,len,flags,to,tolen)
  98. int s;        /* Socket index */
  99. char *buf;    /* User buffer */
  100. int len;    /* Length of buffer */
  101. int flags;    /* Unused; will eventually select oob data, etc */
  102. char *to;    /* Destination, only for datagrams */
  103. int tolen;    /* Length of destination */
  104. {
  105.     register struct mbuf *bp;
  106.  
  107.     bp = qdata(buf,(int16)len);
  108.     return send_mbuf(s,bp,flags,to,tolen);
  109. }
  110. /* Receive a newline-terminated line from a socket, returning # chars read.
  111.  * The end-of-line sequence is recognized and translated into a single '\n'.
  112.  */
  113. int
  114. recvline(s,buf,len)
  115. int s;        /* Socket index */
  116. char *buf;    /* User buffer */
  117. unsigned len;    /* Length of buffer */
  118. {
  119.     int c;
  120.     int cnt = 0;
  121.  
  122.     while(len-- > 1){
  123.         if((c = recvchar(s)) == EOF){
  124.             cnt = -1;
  125.             break;
  126.         }
  127.         if(buf != NULLCHAR)
  128.             *buf++ = c;
  129.         cnt++;
  130.         if(uchar(c) == '\n')
  131.             break;
  132.     }
  133.     if(buf != NULLCHAR)
  134.         *buf = '\0';
  135.     return cnt;
  136. }
  137. #if    defined(ANSIPROTO)
  138. /* Do printf on a user socket */
  139. int
  140. usprintf(int s,char *fmt,...)
  141. {
  142.     va_list args;
  143.     int len;
  144.  
  145.     va_start(args,fmt);
  146.     len = usvprintf(s,fmt,args);
  147.     va_end(args);
  148.     return len;
  149. }
  150. /* Printf on standard output socket */
  151. int
  152. tprintf(char *fmt,...)
  153. {
  154.     va_list args;
  155.     int len;
  156.  
  157.     va_start(args,fmt);
  158.     len = usvprintf(Curproc->output,fmt,args);
  159.     va_end(args);
  160.  
  161. #if 0
  162.     /* Refresh "net> " prompt if necessary. */
  163.  
  164.     if (Curproc->output == Command->output)
  165.         {
  166.         (void) usprintf (Curproc->output, Prompt);
  167.         usflush (Curproc->output);
  168.         }
  169. #endif
  170.  
  171.     return len;
  172. }
  173. /* The guts of printf, uses variable arg version of sprintf */
  174. int
  175. usvprintf(int s,char *fmt, va_list args)
  176. {
  177.     int len,withargs;
  178.     char *buf;
  179.  
  180.     if(strchr(fmt,'%') == NULLCHAR){
  181.         /* Common case optimization: no args, so we don't
  182.          * need vsprintf()
  183.          */
  184.         withargs = 0;
  185.         buf = fmt;
  186.         len = strlen(fmt);
  187.     } else {
  188.         /* Use a default value that is hopefully longer than the
  189.          * biggest output string we'll ever print (!)
  190.          */
  191.         withargs = 1;
  192.         buf = mallocw(SOBUF);
  193.         vsprintf(buf,fmt,args);
  194.         len = strlen(buf);
  195.     }
  196.     if(usputs(s,buf) == EOF)
  197.         len = -1;
  198.     if(withargs)
  199.         free(buf);
  200.     return len;
  201. }
  202. #else
  203. /*VARARGS*/
  204. /* Printf to standard output socket */
  205. int
  206. tprintf(fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  207. char *fmt;        /* Message format */
  208. int arg1,arg2,arg3;    /* Arguments */
  209. int arg4,arg5,arg6;
  210. int arg7,arg8,arg9;
  211. int arg10,arg11,arg12;
  212. {
  213.     return usprintf(Curproc->output,fmt,arg1,arg2,arg3,arg4,arg5,arg6,
  214.         arg7,arg8,arg9,arg10,arg11,arg12);
  215. }
  216. /* Printf to socket. Doesn't use ANSI vsprintf */
  217. int
  218. usprintf(s,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  219. int s;            /* Socket index */
  220. char *fmt;        /* Message format */
  221. int arg1,arg2,arg3;    /* Arguments */
  222. int arg4,arg5,arg6;
  223. int arg7,arg8,arg9;
  224. int arg10,arg11,arg12;
  225. {
  226.     int len,withargs;
  227.     char *buf;
  228.  
  229.     if(strchr(fmt,'%') == NULLCHAR){
  230.         /* No args, so we don't need vsprintf() */
  231.         withargs = 0;
  232.         buf = fmt;
  233.         len = strlen(fmt);
  234.     } else {
  235.         /* Use a default value that is hopefully longer than the
  236.          * biggest output string we'll ever print (!)
  237.          */
  238.         withargs = 1;
  239.         buf = mallocw(SOBUF);
  240.         sprintf(buf,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,
  241.          arg8,arg9,arg10,arg11,arg12);
  242.         len = strlen(buf);
  243.     }
  244.     if(usputs(s,buf) == EOF)
  245.         len = -1;
  246.  
  247.     if(withargs)
  248.         free(buf);
  249.     return len;
  250. }
  251. #endif
  252. /* Buffered putchar to a socket */
  253.  
  254. int usputc(
  255.     int s,
  256.     char c )
  257. {
  258.     struct usock *up;
  259.     register struct mbuf *bp;
  260.     char *cp;
  261.     int newline,len;
  262.  
  263.     if((up = itop(s)) == NULLUSOCK){
  264.         errno = EBADF;
  265.         return -1;
  266.     }
  267.     if(c == '\n' && (up->flag & SOCK_ASCII)){
  268.         newline = 1;
  269.         len = strlen(up->eol);
  270.     } else {
  271.         newline = 0;
  272.         len = 1;
  273.     }
  274.     /* Make sure there's room in the current buffer, if any */
  275.     if((bp = up->obuf) != NULLBUF){
  276.         if((bp->cnt >= bp->size - len) && usflush(s) == -1)
  277.             return EOF;
  278.     }
  279.     if(up->obuf == NULLBUF){
  280.         /* Allocate a buffer of appropriate size */
  281.         switch(up->type){
  282.         case TYPE_NETROML4:
  283.             up->obuf = ambufw(NR4MAXINFO);
  284.             break;
  285.         default:
  286.             up->obuf = ambufw(BUFSIZ);
  287.             break;
  288.         }
  289.     }
  290.     /* Note: the buffer must be larger than the end-of-line sequence! */
  291.     bp = up->obuf;
  292.     cp = &bp->data[bp->cnt];
  293.     if(newline){
  294.         /* Translate into appropriate end-of-line sequence */
  295.         strncpy(cp,up->eol,len);
  296.     } else {
  297.         *cp = c;
  298.     }
  299.     bp->cnt += len;
  300.     /* Flush if necessary */
  301.     if(c == up->flush && up->flush != -1 && usflush(s) == -1)
  302.             return -1;
  303.  
  304.     return (int)uchar(c);
  305. }
  306. /* Put a character to standard output socket */
  307.  
  308. int tputc(char c)
  309. {
  310.     return usputc(Curproc->output,c);
  311. }
  312. #ifndef    oldusputs
  313. /* Buffered puts to a socket */
  314. int
  315. usputs(s,buf)
  316. int s;
  317. char *buf;
  318. {
  319.     register struct usock *up;
  320.     register struct mbuf *bp;
  321.     char *cp,*wp;
  322.     int16 len,clen;
  323.     int doflush;
  324.     int eol_len;
  325.     int16 flushpt;
  326.     int ascii;
  327.  
  328.     if((up = itop(s)) == NULLUSOCK){
  329.         errno = EBADF;
  330.         return EOF;
  331.     }
  332.     ascii = up->flag & SOCK_ASCII;
  333.     if(ascii)
  334.         eol_len = strlen(up->eol);
  335.     doflush = (up->flush != -1) && (strchr(buf,up->flush) != NULLCHAR);
  336.     len = strlen(buf);
  337.  
  338.     while(len != 0){
  339.         if(up->obuf == NULLBUF){
  340.             /* Allocate a buffer of appropriate size */
  341.             switch(up->type){
  342.             case TYPE_NETROML4:
  343.                 clen = NR4MAXINFO;
  344.                 break;
  345.             default:
  346.                 clen = BUFSIZ;
  347.                 break;
  348.             }
  349.             up->obuf = ambufw(clen);
  350.         }
  351.         /* Note: the buffer must be larger than the end-of-line sequence! */
  352.         bp = up->obuf;
  353.         wp = &bp->data[bp->cnt];
  354.         if(ascii && (cp = strchr(buf,'\n')) != NULLCHAR){
  355.             /* Copy up to, but not including, newline */
  356.             clen = cp - buf;
  357.         } else {
  358.             /* Copy whole thing */
  359.             clen = len;
  360.         }
  361.         /* ...but no more than the room available */
  362.         clen = min(clen,bp->size - bp->cnt);
  363.         if(clen != 0){
  364.             memcpy(wp,buf,clen);
  365.             wp += clen;
  366.             bp->cnt += clen;
  367.             buf += clen;
  368.             len -= clen;
  369.         }
  370.         /* Set flush threshold to allow for eol, if enabled */
  371.         if(ascii)
  372.             flushpt = bp->size - eol_len;
  373.         else
  374.             flushpt = bp->size;
  375.  
  376.         if(ascii && *buf == '\n' && bp->cnt < flushpt){
  377.             /* Add appropriate end-of-line sequence */
  378.             strncpy(wp,up->eol,eol_len);
  379.             wp += eol_len;
  380.             bp->cnt += eol_len;
  381.             buf++;    /* Skip newline in buffer */
  382.             len--;
  383.         }
  384.         if(bp->cnt >= flushpt){
  385.             /* Buffer full, flush and get another */
  386.             if(usflush(s) == -1)
  387.                 return EOF;
  388.         }
  389.     }    
  390.     if(doflush && usflush(s) == -1)
  391.         return EOF;
  392.  
  393.     return 0;
  394. }
  395.  
  396. #else
  397.  
  398. int
  399. usputs(s,x)
  400. int s;
  401. register char *x;
  402. {
  403.     while(*x != '\0')
  404.         if(usputc(s,*x++) == EOF)
  405.             return EOF;
  406.     return 0;
  407. }
  408. #endif
  409.  
  410. /* Put a string to standard output socket */
  411. int
  412. tputs(s)
  413. char *s;
  414. {
  415.     return usputs(Curproc->output,s);
  416. }
  417.  
  418. /* Read a raw character from a socket with stream buffering. */
  419. int
  420. rrecvchar(s)
  421. int s;            /* Socket index */
  422. {
  423.     register struct usock *up;
  424.  
  425.     if((up = itop(s)) == NULLUSOCK){
  426.         return EOF;
  427.     }
  428.     /* Replenish if necessary */
  429.     if(up->ibuf == NULLBUF && recv_mbuf(s,&up->ibuf,0,NULLCHAR,0) <= 0)
  430.         return EOF;
  431.  
  432.     return PULLCHAR(&up->ibuf);    /* Returns -1 if eof */
  433. }
  434. /* This function recognizes the end-of-line sequence for the stream
  435.  * and translates it into a single '\n'.
  436.  */
  437. int
  438. recvchar(s)
  439. int s;            /* Socket index */
  440. {
  441.     int c;
  442.     register struct usock *up;
  443.  
  444.     if((up = itop(s)) == NULLUSOCK)
  445.         return EOF;
  446.  
  447.     c = rrecvchar(s);
  448.  
  449.     while (c == '\032' && (up->flag & SOCK_ASCII) != 0)
  450.         c = rrecvchar (s);                /* skip embedded ^Z                    */
  451.  
  452.     if(c != up->eol[0] || !(up->flag & SOCK_ASCII))
  453.         return c;
  454.  
  455.     /* This is the first char of a eol sequence. If the eol sequence is
  456.      * more than one char long, eat the next character in the input stream.
  457.      */
  458.     if(up->eol[1] != '\0'){
  459.         (void)rrecvchar(s);
  460.     }
  461.     return '\n';
  462. }
  463. /* Flush output on a socket stream */
  464. int
  465. usflush(s)
  466. int s;
  467. {
  468.     register struct usock *up;
  469.     struct mbuf *bp;
  470.  
  471.     if((up = itop(s)) == NULLUSOCK)
  472.         return -1;
  473.  
  474.     if(up->obuf != NULLBUF){
  475.         bp = up->obuf;
  476.         up->obuf = NULLBUF;
  477.         return send_mbuf(s,bp,0,NULLCHAR,0);
  478.     }
  479.     return 0;
  480. }
  481. /* Flush output socket */
  482. void
  483. tflush()
  484. {
  485.     usflush(Current->output);
  486. }
  487.  
  488. /* Print prompt and read one character */
  489. int
  490. keywait(prompt,flush)
  491. char *prompt;    /* Optional prompt */
  492. int flush;    /* Flush queued input? */
  493. {
  494.     int c;
  495.     int i;
  496.  
  497.     if(flush && socklen(Curproc->input,1) != 0)
  498.         recv_mbuf(Curproc->input,NULLBUFP,0,NULLCHAR,0); /* flush */
  499.     if(prompt == NULLCHAR)
  500.         prompt = "Hit enter to continue"; 
  501.     tprintf(prompt);
  502.     tflush();
  503.     c = recvchar(Curproc->input);
  504.     /* Get rid of the prompt */
  505.     for(i=strlen(prompt);i != 0;i--)
  506.         tputc('\b');
  507.     for(i=strlen(prompt);i != 0;i--)
  508.         tputc(' ');
  509.     for(i=strlen(prompt);i != 0;i--)
  510.         tputc('\b');
  511.     tflush();
  512.     return (int)c;
  513. }
  514.  
  515. /* Set the end-of-line sequence on a socket */
  516. int
  517. seteol(s,seq)
  518. int s;
  519. char *seq;
  520. {
  521.     register struct usock *up;
  522.  
  523.     if((up = itop(s)) == NULLUSOCK)
  524.         return -1;
  525.  
  526.     if(seq != NULLCHAR)
  527.         strncpy(up->eol,seq,sizeof(up->eol));
  528.     else
  529.         *up->eol = '\0';
  530.     return 0;
  531. }
  532. /* Enable/disable eol translation, return previous state */
  533. int
  534. sockmode(s,mode)
  535. int s,mode;
  536. {
  537.     struct usock *up;
  538.     int prev;
  539.  
  540.     if((up = itop(s)) == NULLUSOCK)
  541.         return -1;
  542.     usflush(s);
  543.     prev = up->flag;
  544.     switch(mode){
  545.     case SOCK_BINARY:
  546.     case SOCK_ASCII:
  547.         up->flag = mode;
  548.         break;
  549.     default:
  550.         break;
  551.     }
  552.     return prev;
  553. }
  554. /* Specify the character to trigger automatic output buffer
  555.  * flushing, or -1 to disable it. Return the previous setting.
  556.  */
  557. int
  558. setflush(s,c)
  559. int s;
  560. int c;
  561. {
  562.     register struct usock *up;
  563.     int old;
  564.  
  565.     if((up = itop(s)) == NULLUSOCK)
  566.         return -1;
  567.  
  568.     old = up->flush;
  569.     up->flush = c;
  570.     return old;
  571. }
  572.